package nl.hu.lcv.agents;

import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.Behaviour;
import jade.core.behaviours.TickerBehaviour;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;

import java.io.IOException;
import java.util.ArrayList;

import nl.hu.lcv.blackboard.client.BlackboardClientUtils;
import nl.hu.lcv.blackboard.data.PostItProtos.PostIt;
import nl.hu.lcv.blackboard.data.PostItProtos.PostItBox;

public class ProductAgent extends Agent 
{
	private Product myProduct = null;
	
	private class KillBehaviour extends TickerBehaviour
	{

		public KillBehaviour(Agent a, long timeout) {
			super(a, timeout);	
			
			
		}

		@Override
		protected void onTick() {
			myAgent.doDelete();
			
		}	
		
	}
		
	private class DiscoverGridBehaviour extends Behaviour
	{
		
		private int step = 0;
		private int bestGridProposal = 0;
		private AID bestGrid = null;
		private int numberOfGrids = 0;
		private MessageTemplate mt;
		
		
		@Override
		public void action() 
		{			
			switch(step)
			{
				case 0:		
					//Look for directors and inform them of new product
					ACLMessage msg = new ACLMessage(ACLMessage.CFP);	
					DFAgentDescription template = new DFAgentDescription(); 
			        ServiceDescription sd = new ServiceDescription(); 
			        sd.setType("Director");
			        template.addServices(sd); 
			        try { 
			          DFAgentDescription[] result = DFService.search(myAgent, template); 
			          for (int i = 0; i < result.length; ++i) { 
			        	  msg.addReceiver(result[i].getName()); 
			        	  numberOfGrids++;
			          } 
			           	msg.setConversationId("Gridpicker");
			          	msg.setContentObject(myProduct);
			        } 
			 		catch (FIPAException fe) { 
				 		fe.printStackTrace(); 
		        	}
					catch (IOException e1) {					
						e1.printStackTrace();
			        }
			        msg.setReplyWith("Grid"+System.currentTimeMillis());
			        mt = MessageTemplate.and(MessageTemplate.MatchConversationId("Gridpicker"),
			        						 MessageTemplate.MatchInReplyTo(msg.getReplyWith()));
			        send(msg);
			        step++;
			        break;
				case 1: 
					//Receive proposals of directors and pick the best
					ACLMessage reply = myAgent.receive(mt);
				
					if(reply != null)
					{						
						System.out.println("Check");
						numberOfGrids--;
						if(reply.getPerformative() == ACLMessage.PROPOSE)
						{							
							int proposal = Integer.parseInt(reply.getContent());
							if (bestGrid == null || proposal > bestGridProposal) {
								bestGridProposal = proposal;
								bestGrid = reply.getSender();
							}																
						}			       
						if(numberOfGrids == 0)
							step++;
					}
					else
						block();
					break;
				case 2:		
													
			        ArrayList<PostIt> arr = new ArrayList<PostIt>();		     
			        int end = myProduct.getSteps().length;
			        for(int i = 0; i < end; i++)
			        {			 			   
			 			  PostIt p = PostIt.newBuilder()
					    			.setOrdinal(i+1)
					    			.setOwner(myProduct.getName())
					    			.setPayload(myProduct.getSteps()[i])
					    			.build();			 			   
			 			   			 			   
			 			   arr.add(p);
		            }
			    	PostItBox postItBox = PostItBox.newBuilder()
							.setZone("BB1")
							.setIsWrite(true)							
			        		.addAllPostIts(arr)
			    			.build();
			        BlackboardClientUtils.writeToBlackboard(postItBox);	
					
					
					ACLMessage GridMessage = new ACLMessage(ACLMessage.ACCEPT_PROPOSAL);
					GridMessage.addReceiver(bestGrid);
					GridMessage.setConversationId("Confirm");
					try {
						GridMessage.setContentObject(myProduct);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					send(GridMessage);			
					
			        step++;
					break;
					
					
					
			}
		}

		@Override
		public boolean done() {
			if(step == 2 && bestGrid == null)
			{
				myAgent.doDelete();		
			}
			return step == 3;
		}
	}
	
	public void setup()
	{
		myProduct = (Product)getArguments()[0];
		addBehaviour(new DiscoverGridBehaviour());		
		addBehaviour(new KillBehaviour(this, 10000));
		
	}
	
	public void takeDown()
	{
		
	}
}
